﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Autofac;
using Autofac.Integration.Mvc;
using IDal;
using DalFactory;
using IBll;
using BllFactory;
using Model;
using Model.DbContext;
using Model.Sys;
using Txy.Dal.Core;
using Txy.IDal.Core;

namespace UI
{
    /// <summary>
    /// 依赖注入Controller、FilterAtrribute
    /// </summary>
    public class IocConfig
    {

        /// <summary>
        /// 创建 MVC容器（包含Filter）
        /// PS：为了使得属性注入生效，项目中重要的对象的生产均采用Autofac的方式
        /// PS：属性为Null时候，才会去触发重新注入
        /// </summary>
        public static void BuildMvcContainer()
        {
            #region 注册Controllers

            #region 方案一(VC分离注册Controllers)

            var builder = new ContainerBuilder();
            //Assembly[] asm = GetAllAssembly("Controllers.dll").ToArray();
            Assembly[] asm = Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath,"Controllers.dll").Select(Assembly.LoadFrom).ToArray();
            builder.RegisterAssemblyTypes(asm).PropertiesAutowired();

            #endregion

            #region 方案二

            //var builder = new ContainerBuilder();
            //builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();//使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册
            //builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();//使用Autofac.WebApi提供的RegisterApiControllers扩展方法来对程序集中所有的ApiController一次性的完成注册

            #endregion

            #endregion

            #region 注册IBllSession(以及其包含的所有属性和属性的属性)

            #region 手动注册

            //builder.Register(a => { return BllSessionUtil.GetCurrentBllSession(); }).As<IBllSession>().PropertiesAutowired();
            //builder.RegisterType<UserInfoBll>().As<IUserInfoBll>().PropertiesAutowired();
            //builder.RegisterType<TestBll>().As<ITestBll>().PropertiesAutowired();

            //builder.RegisterType<DalSession>().As<IDalSession>().PropertiesAutowired();
            //builder.Register(a => { return ConFactory.GetMsSqlCon(); }).As<IDbConnection>().PropertiesAutowired();
            //builder.RegisterType<UserInfoDal>().As<IUserInfoDal>().PropertiesAutowired();
            //builder.RegisterType<TestDal>().As<ITestDal>().PropertiesAutowired();

            #endregion

            #region 自动注册（依赖接口）

            Assembly[] assemblies = Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath, "*.dll").Select(Assembly.LoadFrom).ToArray();
            Type baseType = typeof(IDependency);
            builder.RegisterAssemblyTypes(assemblies)
                .Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
                .Except<BllSession>().Except<DalSession>().Except<ModelContainer>()//以防万一，这里直接排除这三个服务的注册
                .AsSelf().AsImplementedInterfaces()
                .PropertiesAutowired();//InstancePerLifetimeScope();
                                       //.InstancePerHttpRequest();//开启之后，代码中不可手动去生产对象，不然报错。

            #endregion

            #endregion

            #region 补充注册（系统元数据类型,特殊处理接口的注册）

            builder.RegisterType<BaseDalExtend>().As<IBaseDalExtend>().PropertiesAutowired();
            builder.Register(a => { return DbContextUtil.GetCurrentDbContext(); }).As<ModelContainer>().PropertiesAutowired();//每次注入新的的对象
            builder.Register(a => { return DalSessionUtil.GetCurrentDalSession(); }).As<IDalSession>().PropertiesAutowired();//.InstancePerLifetimeScope()
            builder.Register(a => { return BllSessionUtil.GetCurrentBllSession(); }).As<IBllSession>().PropertiesAutowired();//重复注册，以覆盖之前的注册.InstancePerLifetimeScope()

            #endregion

            var container = builder.Build();
            //var config = GlobalConfiguration.Configuration;
            //config.DependencyResolver = new AutofacWebApiDependencyResolver(container);//设置WebApi依赖注入解析器为Autofac提供

            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));//设置Mvc依赖注入解析器为Autofac提供

        }

        #region 加载程序集
        private static List<Assembly> GetAllAssembly(string dllName)
        {
            List<string> pluginpath = FindPlugin(dllName);
            var list = new List<Assembly>();
            foreach (string filename in pluginpath)
            {
                try
                {
                    string asmname = Path.GetFileNameWithoutExtension(filename);
                    if (asmname != string.Empty)
                    {
                        Assembly asm = Assembly.LoadFrom(filename);
                        list.Add(asm);
                    }
                }
                catch (Exception ex)
                {
                    Console.Write(ex.Message);
                }
            }
            return list;
        }
        //查找所有插件的路径
        private static List<string> FindPlugin(string dllName)
        {
            List<string> pluginpath = new List<string>();
           
            string path = AppDomain.CurrentDomain.BaseDirectory;
            string dir = Path.Combine(path, "bin");
            string[] dllList = Directory.GetFiles(dir, dllName);
            if (dllList.Length > 0)
            {
                pluginpath.AddRange(dllList.Select(item => Path.Combine(dir, item.Substring(dir.Length + 1))));
            }
            return pluginpath;
        }
        #endregion

    }
}